package cn.wolfcode.service.impl;

import cn.wolfcode.domain.Permission;
import cn.wolfcode.mapper.PermissionMapper;
import cn.wolfcode.qo.QueryObject;
import cn.wolfcode.service.PermissionService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 权限的服务层
 *
 * @author 杨兴健
 * @Date 2020/7/9 10:34
 */
@Service
public class PermissionServiceImpl implements PermissionService {


    @Autowired
    private PermissionMapper mapper;

    @Autowired
    private ApplicationContext context;

    /**
     * 根据查询条件查询权限并封装为ResultSet对象
     *
     * @param qo
     * @return
     */
    @Override
    public PageInfo<Permission> selectAllByQO(QueryObject qo) {

//        用PageHelper插件开始分页
        PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
        List<Permission> permissions = mapper.selectAllByQO(qo);
//       封装为PageInfo结果集
        PageInfo<Permission> pageInfo = new PageInfo<>(permissions);
        return pageInfo;
    }

    /**
     * 根据id查询权限
     *
     * @param id
     * @return
     */
    @Override
    public Permission selectById(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    /**
     * 跟新权限信息
     *
     * @param permission
     */
    @Override
    public void update(Permission permission) {
        mapper.updateByPrimaryKey(permission);

    }

    /**
     * 添加权限信息
     *
     * @param permission
     */
    @Override
    public void insert(Permission permission) {
        mapper.insert(permission);

    }

    /**
     * 根据id删除权限信息
     *
     * @param id
     */
    @Override
    public void delete(Long id) {
        mapper.deleteByPrimaryKey(id);
    }

    /**
     * 查询全部权限
     *
     * @return
     */
    @Override
    public List<Permission> selectAll() {

        return mapper.selectAll();
    }

    /**
     * 跟新权限
     */
    @Override
    public void reload() {

        //获取带有@Controller注解的bean集合
        Map<String, Object> map = context.getBeansWithAnnotation(Controller.class);
        //获取bean集合的所有控制器
        Collection<Object> controllerBeans = map.values();
        //查询数据库中所有权限的集合
        List<String> expressions = mapper.selectAllExpression();
        //遍历控制器集合，获取每个控制器的对象
        for (Object controllerBean : controllerBeans) {
            //判断控制器是否是被CGlib代理，如果不是，则说明类中没有贴@RequiredPermissinos注解
            if (!AopUtils.isCglibProxy(controllerBean)) {
                continue;
            }
            // 得到控制器父类的的字节码对象（因为贴了@RequiredPermissions,shiro就会对这个类做CGlib动态代理）
            Class<?> clazz = controllerBean.getClass().getSuperclass();

            //得到字节码对象的所有方法
            Method[] methods = clazz.getDeclaredMethods();
            //遍历所有方法
            for (Method method : methods) {
                //判断每个方法是否包含@RequiredPermission注解
                if (method.isAnnotationPresent(RequiresPermissions.class)) {
                    // 获取@RequiredPermission
                    RequiresPermissions annotation = method.getAnnotation(RequiresPermissions.class);
                    //获取注解的value的第二个值
                    String name = annotation.value()[1];
                    //获取注解的value的第一个值
                    String expression = annotation.value()[0];
                    //判断表达式是否被包含在所有的表达式里面
                    if (!expressions.contains(expression)) {
                        // 创建权限模型
                        Permission permission = new Permission();
                        //设置权限模型的名字
                        permission.setName(name);
                        //设置权限模型的表达式
                        permission.setExpression(expression);
                        //更新到数据库
                        mapper.insert(permission);
                    }
                }
            }
        }

    }


}
